Skip to main content

trash-cli — Terminal Trash (Safer Than rm) Safer Delete VPS

On servers, rm is fast—and unforgiving. trash-cli gives you a safety net by moving files to a Trash location (XDG / FreeDesktop Trash spec), keeping metadata like original path and deletion time so you can list and restore what you removed.

When to use trash-cli
  • Before editing/deleting critical files (wp-config.php, .htaccess)
  • When cleaning WordPress logs/cache/uploads but you still want an “undo”
  • In maintenance workflows where mistakes are expensive
Server reality check

Trash is still disk usage. If you trash large backups/media and never prune, your disk can fill up.

Prerequisites​

  • Ubuntu/Debian (or similar Linux VPS)
  • SSH access
  • Common WordPress paths (examples):
    • /var/www/html/ → WP root
    • /var/www/html/wp-content/uploads/ → Media
    • /home/backups/ → Backups

Install & Verify​

sudo apt update
sudo apt install -y trash-cli

Verify:

trash --version || trash-put --version

How It Works​

trash-cli follows the desktop Trash spec (XDG/FreeDesktop). In practice:

  • “Deleting” becomes move to Trash
  • You can audit what you trashed
  • You can restore items to their original location
  • You can prune Trash by age
Where is the Trash stored?

By default (per spec), the user Trash is typically:

echo ~/.local/share/Trash

You’ll usually see subfolders like files/ and info/.

Not a backup system

Trash helps you recover from mistakes, but it’s not a real backup strategy. Use snapshots/backups for long-term safety.

Command Map​

# Safer delete (move to Trash)
trash [FILES...] # often same as: trash-put [FILES...]

# Inspect
trash-list # list trashed items (original path + deletion date)

# Restore
trash-restore # interactive restore selection
trash-restore --overwrite # overwrite destination if needed

# Prune
trash-empty [DAYS] # empty all, or only items older than DAYS

# Permanently remove from Trash by pattern
trash-rm 'GLOB' # delete matching trashed items permanently
trash vs trash-put

On many systems, trash is a convenient wrapper/synonym for trash-put. If trash isn’t available, use trash-put.

Quick Decision Guide​

GoalBest Command
--
Safer delete (keep an undo path)trash file_or_dir
See what’s currently in Trashtrash-list
Restore something you removedtrash-restore
Restore even if file exists alreadytrash-restore --overwrite
Keep Trash under control automaticallytrash-empty 30
Permanently purge only certain trashed filestrash-rm '*.sql'

Most Useful Moves (Ratings)​

Move⭐ RatingWhy It Matters
-:--
Use trash instead of rm for risky deletes⭐⭐⭐⭐⭐Gives you an undo path on production-like systems
trash-restore⭐⭐⭐⭐⭐Brings back files without guesswork (interactive selection)
trash-empty N⭐⭐⭐⭐Simple retention policy (great with cron)
trash-list⭐⭐⭐⭐Fast audit trail of what you deleted
trash-rm⭐⭐⭐Targeted permanent purge (useful, but less frequent)

Best Practices​

  • Prefer trash for anything you might want back.
  • Set a retention policy (example: keep 30 days).
  • Quote globs for trash-rm so your shell doesn’t expand them early.
  • Avoid “blind” cleanup in production paths—always inspect first (trash-list, ls, du -sh).
Don’t blindly alias rm to trash

They are not identical in behavior and expectations (especially in scripts). If you must, use a safer wrapper that warns you rather than silently changing semantics.

Add a daily retention job (cron)​

# Purge items older than 30 days, daily
(crontab -l 2>/dev/null; echo "@daily $(command -v trash-empty) 30") | crontab -

Troubleshooting​

ProblemLikely CauseFix
----
trash: command not foundNot installed or PATH missingInstall via APT/pipx/pip; ensure ~/.local/bin is in PATH
Can’t restore (name collision)File already exists at destinationUse trash-restore --overwrite
“Where did my files go?”Looking in wrong locationCheck ~/.local/share/Trash (user Trash)
Disk still full after “deleting”Trash not prunedRun trash-empty (or trash-empty 30)
trash-rm deletes nothingShell expanded glob before commandQuote pattern: trash-rm '*.log'

Cheat Sheet​

# Safe delete
trash foo.txt
trash dir/

# Audit
trash-list

# Restore
trash-restore
trash-restore --overwrite

# Retention / prune
trash-empty # empty all trash
trash-empty 30 # empty items older than 30 days
trash-rm '*.sql' # permanently purge matching trashed items

# Trash location (typical)
echo ~/.local/share/Trash

Worked Examples (Max 15)

Assumption

WordPress root is /var/www/html.

Safely delete a WordPress debug log​

trash /var/www/html/wp-content/debug.log

Safely move old Nginx logs to Trash​

trash /var/log/nginx/*.log

List trashed items (page through)​

trash-list | less

Restore a mistakenly deleted wp-config.php​

trash-restore

Restore and overwrite an existing placeholder​

trash-restore --overwrite

Empty items older than 7 days​

trash-empty 7

Empty Trash completely (cleanup event)​

trash-empty

Permanently remove only .sql dumps from Trash​

trash-rm '*.sql'

Automate 30-day retention (cron)​

(crontab -l 2>/dev/null; echo "@daily $(command -v trash-empty) 30") | crontab -

Trash multiple paths including directories​

trash /home/backups/*.tar.gz /var/www/html/wp-content/cache

Confirm Trash location​

echo ~/.local/share/Trash

Find a trashed upload quickly (ripgrep)​

trash-list | rg -n 'uploads/.*\.jpg$'

Dry-review before permanent purge​

trash-list | grep '\.log$'

(Then decide whether to run trash-rm '*.log'.)

Simple cleanup ritual​

trash /home/backups/*.old && trash-empty 14

One-liner: find an entry, feed index into restore (advanced)​

idx=$(trash-list | nl -ba | grep 'wp-content/uploads/logo' | awk '{print $1; exit}')
trash-restore <<< "$idx"
Advanced example

This relies on interactive restore behavior and the list ordering. Use it only if you understand what it’s doing.

Mini Quiz​

  1. Which command moves files to Trash, and which command lists what’s inside?
  2. How do you restore a file when the destination already exists?
  3. What does trash-empty 30 do?
  4. Where is the home Trash directory typically stored?
  5. Why is aliasing rm to trash discouraged?